#include<bits/stdc++.h>
using namespace std;
const int M = 995;
const int base = 233;
typedef long long ll;
int get_hash(string s) {
  int res = 0;
  int len=(int)s.size();
  for (int i = 0;i<len; ++i) {
    res = (ll)(res * base + s[i]) % M;
  }
  return res;
}
const int SIZE = 10000;
struct HashTable {
    struct Node {
        int next, value, key;
    } data[SIZE];
    int head[M], size;
    int f(int key) { return key % M; }
    int get(int key) {
        for (int p = head[f(key)]; p; p = data[p].next)
            if (data[p].key == key) return data[p].value;
        return -1;
    }
    int modify(int key, int value) {
        for (int p = head[f(key)]; p; p = data[p].next)
            if (data[p].key == key) return data[p].value = value;
    }
    int add(int key, int value) {
        if (get(key) != -1) return -1;
        data[++size] = (Node) {head[f(key)], value, key};
        head[f(key)] = size;
        return value;
    }
};
#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476

void mainLoop(unsigned int M[]);

unsigned int* add(std::string str);
std::string changeHex(int a);
std::string getMD5(std::string source);
//strBaye的长度
unsigned long strlength;
//A,B,C,D的临时变量
unsigned int atemp;
unsigned int btemp;
unsigned int ctemp;
unsigned int dtemp;
//常量ti unsigned int(abs(sin(i+1))*(2pow32))
const unsigned int k[]={
    0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
    0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
    0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
    0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
    0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
    0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
    0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
    0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
    0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
    0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
    0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
    0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
    0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};
//向左位移数
const unsigned int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
    12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
    4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
    15,21,6,10,15,21,6,10,15,21,6,10,15,21};
const char str16[]="0123456789abcdef";

int printf(const char *, ...);

void mainLoop(unsigned int M[])
{
    unsigned int f,g;
    unsigned int a=atemp;
    unsigned int b=btemp;
    unsigned int c=ctemp;
    unsigned int d=dtemp;
    // printf("a=0x%08x, b=0x%08x, c=0x%08x, d=0x%08x\n", a, b, c, d);

    for (unsigned int i = 0; i < 64; i++)
    {
        if(i<16){
            f=F(b,c,d);
           // printf("f=0x%08x\n", f);
            g=i;
        }else if (i<32) {
            // printf("b=0x%08x, c=0x%08x, d = 0x%08x, ", b, c, d);
            f=G(b,c,d);
            g=(5*i+1)%16;
        }else if(i<48){
            f=H(b,c,d);
            g=(3*i+5)%16;
        }else{
            f=I(b,c,d);
            g=(7*i)%16;
        }
        unsigned int tmp=d;
        d=c;
        c=b;

        // printf("a=0x%08x, f=0x%08x, k[i]=0x%08x, g=0x%08x, m[g]=0x%08x\n", a, f, k[i], g, M[g]);
        // printf("shift x=0x%08x, n=%d\n", (a+f+k[i]+M[g]), s[i] );
        b = b + shift((a+f+k[i]+M[g]), s[i]);
        // printf("after b=0x%08x\n", b);
        a=tmp;
    }
    atemp=a+atemp;
    btemp=b+btemp;
    ctemp=c+ctemp;
    dtemp=d+dtemp;
    //printf("a=0x%08x, b=0x%08x, c=0x%08x, d=0x%08x\n", a, b, c, d);
}
/*
 *填充函数
 *处理后应满足bits≡448(mod512),字节就是bytes≡56（mode64)
 *填充方式为先加一个1,其它位补零
 *最后加上64位的原来长度
 */
unsigned int* add(string str)
{
    unsigned long num=((str.length()+8)/64)+1;         //以512位,64个字节为一组
    unsigned int *strByte = new unsigned int[num*16];    //64/4=16,所以有16个整数
    strlength = num*16;
    for (unsigned int i = 0; i < num*16; i++)
        strByte[i]=0;
    for (unsigned int i=0; i <str.length(); i++) {
        // 一个整数存储四个字节，i>>2表示i/4 一个unsigned int对应4个字节，保存4个字符信息
        strByte[i>>2]|=(str[i])<<((i%4)*8);
    }

    //尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
    strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8);
    /*
     *添加原长度，长度指位的长度，所以要乘8，然后是小端序，所以放在倒数第二个,这里长度只用了32位
     */
    strByte[num*16-2] = (unsigned int)str.length() * 8;
    return strByte;
}
string changeHex(int a)
{
    int b;
    string str1;
    string str="";
    for(int i=0;i<4;i++)
    {
        str1="";
        b=((a>>i*8)%(1<<8))&0xff;   //逆序处理每个字节
        for (int j = 0; j < 2; j++)
        {
            str1.insert(0, 1, str16[b%16]);
            b=b/16;
        }
        str+=str1;
    }
    return str;
}
string getMD5(string source)
{
    atemp=A;    //初始化
    btemp=B;
    ctemp=C;
    dtemp=D;
    unsigned int *strByte=add(source);
    for(unsigned int i=0;i<strlength/16;i++)
    {
        unsigned int num[16];
        for(unsigned int j=0;j<16;j++) {
            num[j] = strByte[i*16+j];
        }
        for (int k = 0; k < 16; k++) {
            //std::cout << num[k] << ",";
        }
        //std::cout << std::endl;
        mainLoop(num);
    }
    return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
}
int total_book_items=0;
int total_users=0;
int total_scmanagers=0;
int total_usmanagers=0;
HashTable user_id;//用户名映射到用户编号
HashTable script_id;//图书名映射到图书编号
HashTable user_password_id;//用户密码映射到用户编号(用户登录认证)
HashTable user_manager_password;//用户管理员认证
HashTable script_manager_password;//图书管理员认证
const int restrain_bro=60;//借书限制时间为60天
const int restrain_bro_exp=1;//违约罚款数
struct brorrow_item{//借书记录条款
    string borer;
    int broer_id;
    string script_name;
    int script_id;
    time_t bro_time;//具体借书时间
};
struct ret_item{//还书记录条款
    string borer;
    int broer_id;
    string script_name;
    int script_id;
    time_t acu_ret_time;//具体的还书时间
    bool is_def;//是否违规
};
struct script_item{//图书结构体的实现
    int id;
    string class_id;//类型编号
    std::string name;//名称
    std::string publisher;//出版社
    std::string Writer;//作者
    long long exp;//单价
    int res_num=0;//库存数量
    string ISBN;//版号
    time_t publisher_time;//出版时间
    vector<brorrow_item>items_b;
    vector<ret_item>items_r;//借还记录
    int num=0;//库存数量
    int has_brorrow=0;//这一类型的书被借走多少本
};
int MAX = 3;
struct Node {
public:
    bool IS_LEAF;
    script_item* key;
    int size;
    Node **ptr;
    friend class BPTree;
    Node();
};

class BPTree {

public:
    Node *root;
    void insertInternal(script_item *val, Node *, Node *);
    void removeInternal(int, Node *, Node *);
    Node *findParent(Node *, Node *);
    BPTree();
    void search(int);
    script_item *Find(int val);
    void insert(script_item *val);
    void remove(int);
    void display(Node *);
    void restore(Node* cursor, vector<script_item*>& books);
    Node *getRoot();
};
BPTree node_sc;//适用于图书管理的树对象
Node::Node() {
    key = new script_item[MAX];
    ptr = new Node *[MAX + 1];
}
Node *BPTree::getRoot() { return root; }

BPTree::BPTree() { root = NULL; }
Node *find(int val,Node *cursor) {
    int i = 0;
    while (i < cursor->size) {
        if (val-(cursor->key[i].id) <= 0) break;
        i++;
    }
    if (cursor->size == i) return NULL;
    else return cursor;
    return find(val,cursor->ptr[i]);
}
script_item* BPTree::Find(int val){//返回具体id的图书指针
    script_item *res;
    Node *cur=find(val,this->getRoot());
    for(int i=0;i<cur->size;i++){
        if(cur->key[i].id==val){
            res=(cur->key+i);
            break;
        }
    }
    return res;
}
void BPTree::insert(script_item *x) {//插入某一个具体的条目
    if (root == NULL) {
        root = new Node;
        root->key[0] =(*x);
        root->IS_LEAF = true;
        root->size = 1;
    } else {
        Node *cursor = root;
        Node *parent;
        while (cursor->IS_LEAF == false) {
            parent = cursor;
            for (int i = 0; i < cursor->size; i++) {
                if ((x->id)< cursor->key[i].id) {
                    cursor = cursor->ptr[i];
                    break;
                }
                if (i == cursor->size - 1) {
                    cursor = cursor->ptr[i + 1];
                    break;
                }
            }
        }
        if (cursor->size < MAX) {
            int i = 0;
            while ((x->id)> cursor->key[i].id and i < cursor->size) i++;
            for (int j = cursor->size; j > i; j--) {
                cursor->key[j] = cursor->key[j - 1];
            }
            cursor->key[i] = (*x);
            cursor->size++;
            cursor->ptr[cursor->size] = cursor->ptr[cursor->size - 1];
            cursor->ptr[cursor->size - 1] = NULL;
        } else {
            Node *newLeaf = new Node;
            script_item virtualNode[MAX + 1];
            for (int i = 0; i < MAX; i++) {
                virtualNode[i] = cursor->key[i];
            }
            int i = 0, j;
            while (x->id > virtualNode[i].id and i < MAX) i++;
            for (int j = MAX + 1; j > i; j--) {
                virtualNode[j] = virtualNode[j - 1];
            }
            virtualNode[i]=(*x);
            newLeaf->IS_LEAF = true;
            cursor->size = (MAX + 1) / 2;
            newLeaf->size = MAX + 1 - (MAX + 1) / 2;
            cursor->ptr[cursor->size] = newLeaf;
            newLeaf->ptr[newLeaf->size] = cursor->ptr[MAX];
            cursor->ptr[MAX] = NULL;
            for (i = 0; i < cursor->size; i++) {
                cursor->key[i] = virtualNode[i];
            }
            for (i = 0, j = cursor->size; i < newLeaf->size; i++, j++) {
                newLeaf->key[i] = virtualNode[j];
            }
            if (cursor == root) {
                Node *newRoot = new Node;
                newRoot->key[0] = newLeaf->key[0];
                newRoot->ptr[0] = cursor;
                newRoot->ptr[1] = newLeaf;
                newRoot->IS_LEAF = false;
                newRoot->size = 1;
                root = newRoot;
            } else {
                insertInternal(&newLeaf->key[0], parent, newLeaf);
            }
        }
    }
}

void BPTree::insertInternal(script_item *x, Node *cursor, Node *child) {
    if (cursor->size < MAX) {
        int i = 0;
        while (x->id > cursor->key[i].id and i < cursor->size) i++;
        for (int j = cursor->size; j > i; j--) {
            cursor->key[j]=(cursor->key[j - 1]);
        }
        for (int j = cursor->size + 1; j > i + 1; j--) {
            cursor->ptr[j] = cursor->ptr[j - 1];
        }
        cursor->key[i] = (*x);
        cursor->size++;
        cursor->ptr[i + 1] = child;
    } else {
        Node *newInternal = new Node;
        script_item virtualKey[MAX + 1];
        Node *virtualPtr[MAX + 2];
        for (int i = 0; i < MAX; i++) {
            virtualKey[i] = cursor->key[i];
        }
        for (int i = 0; i < MAX + 1; i++) {
            virtualPtr[i] = cursor->ptr[i];
        }
        int i = 0, j;
        while (x->id> virtualKey[i].id && i < MAX) i++;
        for (int j = MAX + 1; j > i; j--) {
            virtualKey[j] = virtualKey[j - 1];
        }
        virtualKey[i] =(*x);
        for (int j = MAX + 2; j > i + 1; j--) {
            virtualPtr[j] = virtualPtr[j - 1];
        }
        virtualPtr[i + 1] = child;
        newInternal->IS_LEAF = false;
        cursor->size = (MAX + 1) / 2;
        newInternal->size = MAX - (MAX + 1) / 2;
        for (i = 0, j = cursor->size + 1; i < newInternal->size; i++, j++) {
            newInternal->key[i] = virtualKey[j];
        }
        for (i = 0, j = cursor->size + 1; i < newInternal->size + 1; i++, j++) {
            newInternal->ptr[i] = virtualPtr[j];
        }
        if (cursor == root) {
            Node *newRoot = new Node;
            newRoot->key[0] = cursor->key[cursor->size];
            newRoot->ptr[0] = cursor;
            newRoot->ptr[1] = newInternal;
            newRoot->IS_LEAF = false;
            newRoot->size = 1;
            root = newRoot;
        } else {
            insertInternal(&(cursor->key[cursor->size]), findParent(root, cursor),
                           newInternal);
        }
    }
}

Node *BPTree::findParent(Node *cursor, Node *child) {
    Node *parent;
    if (cursor->IS_LEAF || (cursor->ptr[0])->IS_LEAF) {
        return NULL;
    }
    for (int i = 0; i < cursor->size + 1; i++) {
        if (cursor->ptr[i] == child) {
            parent = cursor;
            return parent;
        } else {
            parent = findParent(cursor->ptr[i], child);
            if (parent != NULL) return parent;
        }
    }
    return parent;
}

void BPTree::remove(int x) {//删除某一id的图书
    if (root == NULL) {
        cout << "The archive is empty!\n";
    } else {
        Node *cursor = root;
        Node *parent;
        int leftSibling, rightSibling;
        while (cursor->IS_LEAF == false) {
            for (int i = 0; i < cursor->size; i++) {
                parent = cursor;
                leftSibling = i - 1;
                rightSibling = i + 1;
                if (x< cursor->key[i].id) {
                    cursor = cursor->ptr[i];
                    break;
                }
                if (i == cursor->size - 1) {
                    leftSibling = i;
                    rightSibling = i + 2;
                    cursor = cursor->ptr[i + 1];
                    break;
                }
            }
        }
        bool found = false;
        int pos;
        for (pos = 0; pos < cursor->size; pos++) {
            if (cursor->key[pos].id== x) {
                found = true;
                break;
            }
        }
        if (!found) {
            cout << "Not found\n";
            return;
        }
        for (int i = pos; i < cursor->size; i++) {
            cursor->key[i]=cursor->key[i + 1];
        }
        cursor->size--;
        if (cursor == root) {
            for (int i = 0; i < MAX + 1; i++) {
                cursor->ptr[i] = NULL;
            }
            if (cursor->size == 0) {
                cout << "Tree died\n";
                delete[] cursor->key;
                delete[] cursor->ptr;
                delete cursor;
                root = NULL;
            }
            return;
        }
        cursor->ptr[cursor->size] = cursor->ptr[cursor->size + 1];
        cursor->ptr[cursor->size + 1] = NULL;
        if (cursor->size >= (MAX + 1) / 2) {
            return;
        }
        if (leftSibling >= 0) {
            Node *leftNode = parent->ptr[leftSibling];
            if (leftNode->size >= (MAX + 1) / 2 + 1) {
                for (int i = cursor->size; i > 0; i--) {
                    cursor->key[i] = cursor->key[i - 1];
                }
                cursor->size++;
                cursor->ptr[cursor->size] = cursor->ptr[cursor->size - 1];
                cursor->ptr[cursor->size - 1] = NULL;
                cursor->key[0] = leftNode->key[leftNode->size - 1];
                leftNode->size--;
                leftNode->ptr[leftNode->size] = cursor;
                leftNode->ptr[leftNode->size + 1] = NULL;
                parent->key[leftSibling] = cursor->key[0];
                return;
            }
        }
        if (rightSibling <= parent->size) {
            Node *rightNode = parent->ptr[rightSibling];
            if (rightNode->size >= (MAX + 1) / 2 + 1) {
                cursor->size++;
                cursor->ptr[cursor->size] = cursor->ptr[cursor->size - 1];
                cursor->ptr[cursor->size - 1] = NULL;
                cursor->key[cursor->size - 1] = rightNode->key[0];
                rightNode->size--;
                rightNode->ptr[rightNode->size] = rightNode->ptr[rightNode->size + 1];
                rightNode->ptr[rightNode->size + 1] = NULL;
                for (int i = 0; i < rightNode->size; i++) {
                    rightNode->key[i] = rightNode->key[i + 1];
                }
                parent->key[rightSibling - 1] = rightNode->key[0];
                return;
            }
        }
        if (leftSibling >= 0) {
            Node *leftNode = parent->ptr[leftSibling];
            for (int i = leftNode->size, j = 0; j < cursor->size; i++, j++) {
                leftNode->key[i] = cursor->key[j];
            }
            leftNode->ptr[leftNode->size] = NULL;
            leftNode->size += cursor->size;
            leftNode->ptr[leftNode->size] = cursor->ptr[cursor->size];
            removeInternal(parent->key[leftSibling].id, parent, cursor);
            delete[] cursor->key;
            delete[] cursor->ptr;
            delete cursor;
        } else if (rightSibling <= parent->size) {
            Node *rightNode = parent->ptr[rightSibling];
            for (int i = cursor->size, j = 0; j < rightNode->size; i++, j++) {
                cursor->key[i] = rightNode->key[j];
            }
            cursor->ptr[cursor->size] = NULL;
            cursor->size += rightNode->size;
            cursor->ptr[cursor->size] = rightNode->ptr[rightNode->size];
            cout << "Merging two leaf nodes\n";
            removeInternal(parent->key[rightSibling - 1].id, parent, rightNode);
            delete[] rightNode->key;
            delete[] rightNode->ptr;
            delete rightNode;
        }
    }
}

void BPTree::removeInternal(int x, Node *cursor, Node *child) {
    if (cursor == root) {
        if (cursor->size == 1) {
            if (cursor->ptr[1] == child) {
                delete[] child->key;
                delete[] child->ptr;
                delete child;
                root = cursor->ptr[0];
                delete[] cursor->key;
                delete[] cursor->ptr;
                delete cursor;
                cout << "Changed root node\n";
                return;
            } else if (cursor->ptr[0] == child) {
                delete[] child->key;
                delete[] child->ptr;
                delete child;
                root = cursor->ptr[1];
                delete[] cursor->key;
                delete[] cursor->ptr;
                delete cursor;
                cout << "Changed root node\n";
                return;
            }
        }
    }
    int pos;
    for (pos = 0; pos < cursor->size; pos++) {
        if (cursor->key[pos].id== x) {
            break;
        }
    }
    for (int i = pos; i < cursor->size; i++) {
        cursor->key[i] = cursor->key[i + 1];
    }
    for (pos = 0; pos < cursor->size + 1; pos++) {
        if (cursor->ptr[pos] == child) {
            break;
        }
    }
    for (int i = pos; i < cursor->size + 1; i++) {
        cursor->ptr[i] = cursor->ptr[i + 1];
    }
    cursor->size--;
    if (cursor->size >= (MAX + 1) / 2 - 1) {
        return;
    }
    if (cursor == root) return;
    Node *parent = findParent(root, cursor);
    int leftSibling, rightSibling;
    for (pos = 0; pos < parent->size + 1; pos++) {
        if (parent->ptr[pos] == cursor) {
            leftSibling = pos - 1;
            rightSibling = pos + 1;
            break;
        }
    }
    if (leftSibling >= 0) {
        Node *leftNode = parent->ptr[leftSibling];
        if (leftNode->size >= (MAX + 1) / 2) {
            for (int i = cursor->size; i > 0; i--) {
                cursor->key[i] = cursor->key[i - 1];
            }
            cursor->key[0] = parent->key[leftSibling];
            parent->key[leftSibling] = leftNode->key[leftNode->size - 1];
            for (int i = cursor->size + 1; i > 0; i--) {
                cursor->ptr[i] = cursor->ptr[i - 1];
            }
            cursor->ptr[0] = leftNode->ptr[leftNode->size];
            cursor->size++;
            leftNode->size--;
            return;
        }
    }
    if (rightSibling <= parent->size) {
        Node *rightNode = parent->ptr[rightSibling];
        if (rightNode->size >= (MAX + 1) / 2) {
            cursor->key[cursor->size] = parent->key[pos];
            parent->key[pos] = rightNode->key[0];
            for (int i = 0; i < rightNode->size - 1; i++) {
                rightNode->key[i] = rightNode->key[i + 1];
            }
            cursor->ptr[cursor->size + 1] = rightNode->ptr[0];
            for (int i = 0; i < rightNode->size; ++i) {
                rightNode->ptr[i] = rightNode->ptr[i + 1];
            }
            cursor->size++;
            rightNode->size--;
            return;
        }
    }
    if (leftSibling >= 0) {
        Node *leftNode = parent->ptr[leftSibling];
        leftNode->key[leftNode->size] = parent->key[leftSibling];
        for (int i = leftNode->size + 1, j = 0; j < cursor->size; j++) {
            leftNode->key[i] = cursor->key[j];
        }
        for (int i = leftNode->size + 1, j = 0; j < cursor->size + 1; j++) {
            leftNode->ptr[i] = cursor->ptr[j];
            cursor->ptr[j] = NULL;
        }
        leftNode->size += cursor->size + 1;
        cursor->size = 0;
        removeInternal(parent->key[leftSibling].id, parent, cursor);
    } else if (rightSibling <= parent->size) {
        Node *rightNode = parent->ptr[rightSibling];
        cursor->key[cursor->size] = parent->key[rightSibling - 1];
        for (int i = cursor->size + 1, j = 0; j < rightNode->size; j++) {
            cursor->key[i] = rightNode->key[j];
        }
        for (int i = cursor->size + 1, j = 0; j < rightNode->size + 1; j++) {
            cursor->ptr[i] = rightNode->ptr[j];
            rightNode->ptr[j] = NULL;
        }
        cursor->size += rightNode->size + 1;
        rightNode->size = 0;
        removeInternal(parent->key[rightSibling - 1].id, parent, rightNode);
    }
}

void BPTree::display(Node *cursor=node_sc.getRoot()) {
    if (cursor != NULL) {
        for (int i = 0; i < cursor->size; i++) {
            cout << cursor->key[i].id<< " ";
        }
        cout << "\n";
        if (cursor->IS_LEAF != true) {
            for (int i = 0; i < cursor->size + 1; i++) {
                display(cursor->ptr[i]);
            }
        }
    }
}
class base_user{
public:
    base_user();//构造函数
    void BorrowBook(std::string);//借书
    void ReturnBook(std::string);//还书
    void DisplayRecord();
    void DisplayMesBor();
    void ChangeDebt();

public:
    int user_ID = 0;
    string password = "";
    string user_name = "小帅";
    string user_dep = "信息学部";
    
    vector<ret_item> ret;
    vector<brorrow_item> bro;
    int book_id[30] = { 0 };
    int cnt=0;
    int debt = 0;
    int book_number = 30;
    int freeze_flag = 0;

};
base_user::base_user(){
    user_ID = 0;
    user_name = "小帅";
    user_dep = "信息学部";
    string password = "";

    book_id[30] = { 0 };
    debt = 0;
    book_number = 30;
    freeze_flag = 0;
}


void base_user::BorrowBook(std::string Name){//借书的功能函数
    if(freeze_flag){
        puts("该用户已被冻结!\n");
        return;
    }
    int val=script_id.get(get_hash(Name));
    if(val==-1){
        puts("查无此书!");
        return;
    }
    script_item *item=node_sc.Find(val);
    if(item->has_brorrow==item->res_num){
        puts("暂无库存!");
        return;
    }
    puts("借书成功!");
    item->has_brorrow++;
    book_id[++cnt]=val;
    cout<<"名称: "<< Name<< endl<< "出版社: "<< item->publisher<< 
        endl<<"作者: "<< item->Writer<< endl<< "版号: "<< item->ISBN<< endl;
    cout<< "库存数量: "<< ((item->res_num)-(item->has_brorrow))<< endl;
    time_t bro_time = time(&bro_time);
    bro.push_back({user_name,user_ID,item->name,item->id,bro_time});
    item->items_b.push_back(bro.back());
}
void base_user::ReturnBook(std::string Name){//还书的功能函数
    int val=script_id.get(get_hash(Name));
    if(val==-1){
        puts("查无此书!");
    }
    script_item *item=node_sc.Find(val);
    item->has_brorrow--;
    time_t ret_time = time(&ret_time),bro_time;
    bool f=0;
    brorrow_item pas;
    for(auto c:bro){
        if(c.script_id==val){
            bro_time=c.bro_time;
            pas=c;
            f=1;
        }
    }
    if(!f){
        puts("未查询到借阅记录!\n");
        return;
    }
    puts("查找到的借阅记录为: ");    
    cout<<"借阅时间: "<<ctime(&pas.bro_time)<<endl;
    bool temp_is_def = (ret_time - bro_time) - restrain_bro * 24 * 3600>=0?1:0;
    if(temp_is_def){
        puts("超过规定的还书时间!\n");
        debt+=1;
    }
    if(debt==5){
        freeze_flag=true;
        puts("该用户已被冻结!\n");
    }
    ret.push_back({ user_name, user_ID , item->name,item->id ,ret_time, temp_is_def});
    item->items_r.push_back(ret.back());
}
void base_user::DisplayMesBor(){//展示全部的借还信息
    puts("展示全部的借阅信息!");
    int cnt = 0;
    for(auto c:bro){
        cout<<++cnt<<"."<<endl;
        cout<<"借书用户: "<<c.borer<<endl<<"图书: "<<c.script_name<<endl<<"借阅时间: "<<ctime(&c.bro_time)<<endl;
    }  
    puts("展示全部的还书信息: ");
    cnt=0;
    for(auto c:ret){
        cout<<++cnt<<"."<<endl;
        cout<<"借书用户: "<<c.borer<<endl<<"图书: "<<c.script_name<<endl<<"归还时间: "<<ctime(&c.acu_ret_time)<<endl;
    }
}
void base_user::ChangeDebt(){
        debt=0;
        freeze_flag=false;
        cout<<"欠款 "<<debt<<"元"<<"已缴纳完成!\n";
        return;
}//缴纳罚金
bool IsNum(string str);
bool User_Authentication(string password);
bool User_Manager_Authentication(string password);
bool Script_Manager_Authentication(string password);
bool User_Register(int key,int value);
bool User_Manager_Register(string password);
bool Script_Manager_Register(string password);
bool User_Password_Modify(string password);
bool User_Manager_Password_Modify(string password);
bool Script_Manager_Password_Modify(string password);
bool IsNum(string str){
    for (int i = 0; i < str.size(); i++){
        int tmp = (int)str[i];
        if (tmp >= 48 && tmp <= 57)continue;
        else return false;
    }
    return true;
}
//用户登录认证
bool User_Authentication(string password){
    int key= get_hash( getMD5(password));
    if(user_password_id.get(key) ==-1){
        puts("未经注册的用户!");
        return false;
    }else{
        puts("登陆成功!");
        return true;
    }
}
//用户管理员登录认证
bool User_Manager_Authentication(string password){
    int key = get_hash(getMD5(password));
    if(user_manager_password.get(key) ==-1){
        puts("未经注册的管理员!");
        return false;
    }else{
        puts("登陆成功!");
        return true;
    }
}
//图书管理员登录认证
bool Script_Manager_Authentication(string password){
    int key= get_hash(getMD5(password));
    if(script_manager_password.get(key) == -1){
        puts("未经认证的管理员!");
        return false;
    }else{
        puts("登陆成功!");
        return false;
    }
}
//用户注册,全局变量total_users自加
bool User_Register(int key,int value){
    user_password_id.add(key,value);
    return true;
}
//用户管理员注册
bool User_Manager_Register(string password){
    int key= get_hash(getMD5(password));
    if(user_manager_password.get(key)!=-1){
        puts("该账户已经注册!");
        return false;
    }
    puts("注册成功!");
    user_manager_password.add(key,++total_usmanagers);
    return true;
}
//图书管理员注册
bool Script_Manager_Register(string password){
    int key=get_hash(getMD5(password));
    if(script_manager_password.get(key)!=-1){
        puts("该用户已注册!");
        return false;
    }
    script_manager_password.add(key,++total_scmanagers);
    puts("注册成功!");
    return true;
}
//用户密码修改
bool User_Password_Modify(string password){
    int key= get_hash(getMD5(password));
    int value=user_password_id.get(key);
    string newpass;
    puts("请输入新的用户密码:");
    std::cin>>newpass;
    user_password_id.modify(key,-1);
    user_password_id.add(get_hash(getMD5(newpass)),value);
    return true;
}
//用户管理员密码修改
bool User_Manager_Password_Modify(string password){
    int key  = get_hash(getMD5(password));
    int value=user_manager_password.get(key);
    string newpass;
    puts("请输入新的用户管理员密码:");
    std::cin>>newpass;
    user_manager_password.modify(key,-1);
    user_manager_password.add(get_hash(getMD5(newpass)),value);
    return true;
}
//图书管理员密码修改
bool Script_Manager_Password_Modify(string password){
    int key  = get_hash(getMD5(password));
    int value=script_manager_password.get(key);
    string newpass;
    puts("请输入新的图书管理员密码:");
    std::cin>>newpass;
    script_manager_password.modify(key,-1);
    script_manager_password.add(get_hash(getMD5(newpass)),value);
    return true;
}

class script_manager {
public:
    script_manager();
    script_manager(string sm_password);
    void inputbook(script_item* input, int n);
    void removebook(std::string name, int n);
    void display_by_publisher(std::string publisher);
    void display_by_writer(std::string Writer);
    void display_bro(std::string name);

public:
    string sm_password;
};
void traverse_by_publisher(std::string publisher, vector<script_item>& rec, Node *cursor);
void traverse_by_writer(std::string Writer, vector<script_item>& rec, Node* cursor);
script_manager::script_manager(){
    string sm_password = "";
};
script_manager::script_manager(string sm_password):sm_password(sm_password) {}
void script_manager::inputbook(script_item* input, int n) {
    int val = script_id.get(get_hash(input->name));
    puts("录入图书为: ");
    cout << "名称: " << input->name << endl << "出版社: " << input->publisher << endl
        << "作者: " << input->Writer << endl << "版号: " << input->ISBN << endl;
    if (val == -1) {
        script_id.add(get_hash(input->name), ++total_book_items);
        input->id=total_book_items;
        node_sc.insert(input);
        script_item* item = node_sc.Find(total_book_items);
        item->res_num += n;
        return;
    }
    script_item* item = node_sc.Find(val);
    item->res_num += n;
    return;
}
void script_manager::removebook(std::string name, int n) {
    int val = script_id.get(get_hash(name));
    if (val == -1) {
        puts("该条目不存在! ");
        return;
    }
    script_item* item = node_sc.Find(val);
    item->res_num-=n;
    if(item->res_num<0){
        item->res_num=0;
    }
    puts("删除成功!");
    cout<<"剩余库存数量: "<<item->res_num<<endl;
    return;
}
void traverse_by_publisher(std::string publisher, vector<script_item>& rec, Node* cursor = node_sc.getRoot()) {
    if (cursor == NULL) {
        return;
    }
    for (int i = 0; i < cursor->size; i++) {
        if (cursor->key[i].publisher == publisher) {
            rec.push_back(cursor->key[i]);
        }
    }
    if (!cursor->IS_LEAF) {
        for (int i = 0; i < cursor->size + 1; i++) {
            traverse_by_publisher(publisher,rec,cursor->ptr[i]);
        }
    }
}
void script_manager::display_by_publisher(std::string publisher) {
    vector<script_item>vec;
    traverse_by_publisher(publisher, vec,node_sc.getRoot());
    puts("该出版社下的图书为: ");
    int cnt=0;
    for(auto c:vec){
        cout<<++cnt<<"."<<endl;
        cout<<"名称: "<<c.name<<endl<<"作者: "<<c.Writer<<"库存数量: "<<c.res_num<<endl<<"版号: "<<c.ISBN<<endl;
    }
}
void traverse_by_writer(std::string Writer, vector<script_item>& rec, Node* cursor) {
    if (cursor == NULL) {
        return;
    }
    for (int i = 0; i < cursor->size; i++) {
        if (cursor->key[i].Writer == Writer) {
            rec.push_back(cursor->key[i]);
        }
    }
    if (!cursor->IS_LEAF) {
        for (int i = 0; i < cursor->size + 1; i++) {
            traverse_by_publisher(Writer,rec,cursor->ptr[i]);
        }
    }
}
void script_manager::display_by_writer(std::string Writer) {
    vector<script_item>vec;
    traverse_by_publisher(Writer,vec,node_sc.getRoot());  
    puts("该作者名下的图书有: ");
    int cnt=0;
    for(auto c:vec){
        cout<<++cnt<<"."<<endl;
        cout<<"名称: "<<c.name<<endl<<"出版社: "<<c.publisher<<endl<<"版号: "<<c.ISBN<<endl<<"库存数量: "<<c.res_num<<endl;
    }
}
void script_manager::display_bro(std::string name) {
    int val = script_id.get(get_hash(name));
    if (val == -1) {
        puts("该条目不存在!");
        return;
    }
    script_item *input=node_sc.Find(val);
    vector<brorrow_item>v=input->items_b;
    puts("该图书的借阅信息为: ");
    for(auto c:v){
       cout<<"用户: "<<c.borer<<endl<<"图书: "<<c.script_name<<endl<<"具体的还书时间: "<<ctime(&c.bro_time)<<endl;
    }
}
struct Node_usr{
public:
    bool IS_LEAF;
    base_user *key;
    int size;
    Node_usr **ptr;
    friend class BPTree_usr;
    Node_usr();
};

class BPTree_usr {
public:
    Node_usr *root;
    void insertInternal(base_user *val, Node_usr*, Node_usr *);
    void removeInternal(int, Node_usr *, Node_usr *);
    Node_usr *findParent(Node_usr *, Node_usr *);
    BPTree_usr();
    base_user *Find(int);
    void search(int);
    void insert(base_user *val);
    void remove(int);
    void display(Node_usr *);
    Node_usr *getRoot();
};

BPTree_usr node_usr;
Node_usr::Node_usr() {
    key = new base_user[MAX];
    ptr = new Node_usr *[MAX + 1];
}

BPTree_usr::BPTree_usr() { root = NULL; }
Node_usr *BPTree_usr::getRoot() { return root; }//获取根:统一以根节点为参数
Node_usr *find(int val,Node_usr *cursor) {
    int i = 0;
    while (i < cursor->size) {
        if (val-(cursor->key[i].user_ID) <= 0) break;
        i++;
    }
    if (cursor->size == i) return NULL;
    else return cursor;
    return find(val,cursor->ptr[i]);
}
base_user * BPTree_usr::Find(int val){//根据id查找参数
    int i=0;
    base_user* res;
    Node_usr *cur=find(val,getRoot());
    while(i<cur->size){
        if(val==cur->key[i].user_ID){
            res=cur->key+i;
            break;
        }
        i++;
    }
    return res;
}
void BPTree_usr::insert(base_user *x) {//插入某一个具体的用户,指向一个具体用户的指针
    if (root == NULL) {
        root = new Node_usr;
        root->key[0] =(*x);
        root->IS_LEAF = true;
        root->size = 1;
    } else {
        Node_usr *cursor = root;
        Node_usr *parent;
        while (cursor->IS_LEAF == false) {
            parent = cursor;
            for (int i = 0; i < cursor->size; i++) {
                if ((x->user_ID)< cursor->key[i].user_ID) {
                    cursor = cursor->ptr[i];
                    break;
                }
                if (i == cursor->size - 1) {
                    cursor = cursor->ptr[i + 1];
                    break;
                }
            }
        }
        if (cursor->size < MAX) {
            int i = 0;
            while ((x->user_ID)> cursor->key[i].user_ID and i < cursor->size) i++;
            for (int j = cursor->size; j > i; j--) {
                cursor->key[j] = cursor->key[j - 1];
            }
            cursor->key[i] = (*x);
            cursor->size++;
            cursor->ptr[cursor->size] = cursor->ptr[cursor->size - 1];
            cursor->ptr[cursor->size - 1] = NULL;
        } else {
            Node_usr *newLeaf = new Node_usr;
            base_user virtualNode[MAX + 1];
            for (int i = 0; i < MAX; i++) {
                virtualNode[i] = cursor->key[i];
            }
            int i = 0, j;
            while (x->user_ID > virtualNode[i].user_ID and i < MAX) i++;
            for (int j = MAX + 1; j > i; j--) {
                virtualNode[j] = virtualNode[j - 1];
            }
            virtualNode[i]=(*x);
            newLeaf->IS_LEAF = true;
            cursor->size = (MAX + 1) / 2;
            newLeaf->size = MAX + 1 - (MAX + 1) / 2;
            cursor->ptr[cursor->size] = newLeaf;
            newLeaf->ptr[newLeaf->size] = cursor->ptr[MAX];
            cursor->ptr[MAX] = NULL;
            for (i = 0; i < cursor->size; i++) {
                cursor->key[i] = virtualNode[i];
            }
            for (i = 0, j = cursor->size; i < newLeaf->size; i++, j++) {
                newLeaf->key[i] = virtualNode[j];
            }
            if (cursor == root) {
                Node_usr *newRoot = new Node_usr;
                newRoot->key[0] = newLeaf->key[0];
                newRoot->ptr[0] = cursor;
                newRoot->ptr[1] = newLeaf;
                newRoot->IS_LEAF = false;
                newRoot->size = 1;
                root = newRoot;
            } else {
                insertInternal(&newLeaf->key[0], parent, newLeaf);
            }
        }
    }
}

void BPTree_usr::insertInternal(base_user *x, Node_usr *cursor, Node_usr *child) {
    if (cursor->size < MAX) {
        int i = 0;
        while (x->user_ID > cursor->key[i].user_ID and i < cursor->size) i++;
        for (int j = cursor->size; j > i; j--) {
            cursor->key[j]=(cursor->key[j - 1]);
        }
        for (int j = cursor->size + 1; j > i + 1; j--) {
            cursor->ptr[j] = cursor->ptr[j - 1];
        }
        cursor->key[i] = (*x);
        cursor->size++;
        cursor->ptr[i + 1] = child;
    } else {
        Node_usr *newInternal = new Node_usr;
        base_user virtualKey[MAX + 1];
        Node_usr *virtualPtr[MAX + 2];
        for (int i = 0; i < MAX; i++) {
            virtualKey[i] = cursor->key[i];
        }
        for (int i = 0; i < MAX + 1; i++) {
            virtualPtr[i] = cursor->ptr[i];
        }
        int i = 0, j;
        while (x->user_ID> virtualKey[i].user_ID && i < MAX) i++;
        for (int j = MAX + 1; j > i; j--) {
            virtualKey[j] = virtualKey[j - 1];
        }
        virtualKey[i] =(*x);
        for (int j = MAX + 2; j > i + 1; j--) {
            virtualPtr[j] = virtualPtr[j - 1];
        }
        virtualPtr[i + 1] = child;
        newInternal->IS_LEAF = false;
        cursor->size = (MAX + 1) / 2;
        newInternal->size = MAX - (MAX + 1) / 2;
        for (i = 0, j = cursor->size + 1; i < newInternal->size; i++, j++) {
            newInternal->key[i] = virtualKey[j];
        }
        for (i = 0, j = cursor->size + 1; i < newInternal->size + 1; i++, j++) {
            newInternal->ptr[i] = virtualPtr[j];
        }
        if (cursor == root) {
            Node_usr *newRoot = new Node_usr;
            newRoot->key[0] = cursor->key[cursor->size];
            newRoot->ptr[0] = cursor;
            newRoot->ptr[1] = newInternal;
            newRoot->IS_LEAF = false;
            newRoot->size = 1;
            root = newRoot;
        } else {
            insertInternal(&(cursor->key[cursor->size]), findParent(root, cursor),
                           newInternal);
        }
    }
}

Node_usr *BPTree_usr::findParent(Node_usr *cursor, Node_usr *child) {
    Node_usr *parent;
    if (cursor->IS_LEAF || (cursor->ptr[0])->IS_LEAF) {
        return NULL;
    }
    for (int i = 0; i < cursor->size + 1; i++) {
        if (cursor->ptr[i] == child) {
            parent = cursor;
            return parent;
        } else {
            parent = findParent(cursor->ptr[i], child);
            if (parent != NULL) return parent;
        }
    }
    return parent;
}

void BPTree_usr::remove(int x) {//删除某一id的用户
    if (root == NULL) {
        cout << "Tree empty\n";
    } else {
        Node_usr *cursor = root;
        Node_usr *parent;
        int leftSibling, rightSibling;
        while (cursor->IS_LEAF == false) {
            for (int i = 0; i < cursor->size; i++) {
                parent = cursor;
                leftSibling = i - 1;
                rightSibling = i + 1;
                if (x< cursor->key[i].user_ID) {
                    cursor = cursor->ptr[i];
                    break;
                }
                if (i == cursor->size - 1) {
                    leftSibling = i;
                    rightSibling = i + 2;
                    cursor = cursor->ptr[i + 1];
                    break;
                }
            }
        }
        bool found = false;
        int pos;
        for (pos = 0; pos < cursor->size; pos++) {
            if (cursor->key[pos].user_ID== x) {
                found = true;
                break;
            }
        }
        if (!found) {
            cout << "Not found\n";
            return;
        }
        for (int i = pos; i < cursor->size; i++) {
            cursor->key[i]=cursor->key[i + 1];
        }
        cursor->size--;
        if (cursor == root) {
            for (int i = 0; i < MAX + 1; i++) {
                cursor->ptr[i] = NULL;
            }
            if (cursor->size == 0) {
                cout << "Tree died\n";
                delete[] cursor->key;
                delete[] cursor->ptr;
                delete cursor;
                root = NULL;
            }
            return;
        }
        cursor->ptr[cursor->size] = cursor->ptr[cursor->size + 1];
        cursor->ptr[cursor->size + 1] = NULL;
        if (cursor->size >= (MAX + 1) / 2) {
            return;
        }
        if (leftSibling >= 0) {
            Node_usr *leftNode = parent->ptr[leftSibling];
            if (leftNode->size >= (MAX + 1) / 2 + 1) {
                for (int i = cursor->size; i > 0; i--) {
                    cursor->key[i] = cursor->key[i - 1];
                }
                cursor->size++;
                cursor->ptr[cursor->size] = cursor->ptr[cursor->size - 1];
                cursor->ptr[cursor->size - 1] = NULL;
                cursor->key[0] = leftNode->key[leftNode->size - 1];
                leftNode->size--;
                leftNode->ptr[leftNode->size] = cursor;
                leftNode->ptr[leftNode->size + 1] = NULL;
                parent->key[leftSibling] = cursor->key[0];
                return;
            }
        }
        if (rightSibling <= parent->size) {
            Node_usr *rightNode = parent->ptr[rightSibling];
            if (rightNode->size >= (MAX + 1) / 2 + 1) {
                cursor->size++;
                cursor->ptr[cursor->size] = cursor->ptr[cursor->size - 1];
                cursor->ptr[cursor->size - 1] = NULL;
                cursor->key[cursor->size - 1] = rightNode->key[0];
                rightNode->size--;
                rightNode->ptr[rightNode->size] = rightNode->ptr[rightNode->size + 1];
                rightNode->ptr[rightNode->size + 1] = NULL;
                for (int i = 0; i < rightNode->size; i++) {
                    rightNode->key[i] = rightNode->key[i + 1];
                }
                parent->key[rightSibling - 1] = rightNode->key[0];
                return;
            }
        }
        if (leftSibling >= 0) {
            Node_usr *leftNode = parent->ptr[leftSibling];
            for (int i = leftNode->size, j = 0; j < cursor->size; i++, j++) {
                leftNode->key[i] = cursor->key[j];
            }
            leftNode->ptr[leftNode->size] = NULL;
            leftNode->size += cursor->size;
            leftNode->ptr[leftNode->size] = cursor->ptr[cursor->size];
            removeInternal(parent->key[leftSibling].user_ID, parent, cursor);
            delete[] cursor->key;
            delete[] cursor->ptr;
            delete cursor;
        } else if (rightSibling <= parent->size) {
            Node_usr *rightNode = parent->ptr[rightSibling];
            for (int i = cursor->size, j = 0; j < rightNode->size; i++, j++) {
                cursor->key[i] = rightNode->key[j];
            }
            cursor->ptr[cursor->size] = NULL;
            cursor->size += rightNode->size;
            cursor->ptr[cursor->size] = rightNode->ptr[rightNode->size];
            cout << "Merging two leaf nodes\n";
            removeInternal(parent->key[rightSibling - 1].user_ID, parent, rightNode);
            delete[] rightNode->key;
            delete[] rightNode->ptr;
            delete rightNode;
        }
    }
}

void BPTree_usr::removeInternal(int x, Node_usr *cursor, Node_usr *child) {
    if (cursor == root) {
        if (cursor->size == 1) {
            if (cursor->ptr[1] == child) {
                delete[] child->key;
                delete[] child->ptr;
                delete child;
                root = cursor->ptr[0];
                delete[] cursor->key;
                delete[] cursor->ptr;
                delete cursor;
                cout << "Changed root node\n";
                return;
            } else if (cursor->ptr[0] == child) {
                delete[] child->key;
                delete[] child->ptr;
                delete child;
                root = cursor->ptr[1];
                delete[] cursor->key;
                delete[] cursor->ptr;
                delete cursor;
                cout << "Changed root node\n";
                return;
            }
        }
    }
    int pos;
    for (pos = 0; pos < cursor->size; pos++) {
        if (cursor->key[pos].user_ID== x) {
            break;
        }
    }
    for (int i = pos; i < cursor->size; i++) {
        cursor->key[i] = cursor->key[i + 1];
    }
    for (pos = 0; pos < cursor->size + 1; pos++) {
        if (cursor->ptr[pos] == child) {
            break;
        }
    }
    for (int i = pos; i < cursor->size + 1; i++) {
        cursor->ptr[i] = cursor->ptr[i + 1];
    }
    cursor->size--;
    if (cursor->size >= (MAX + 1) / 2 - 1) {
        return;
    }
    if (cursor == root) return;
    Node_usr *parent = findParent(root, cursor);
    int leftSibling, rightSibling;
    for (pos = 0; pos < parent->size + 1; pos++) {
        if (parent->ptr[pos] == cursor) {
            leftSibling = pos - 1;
            rightSibling = pos + 1;
            break;
        }
    }
    if (leftSibling >= 0) {
        Node_usr *leftNode = parent->ptr[leftSibling];
        if (leftNode->size >= (MAX + 1) / 2) {
            for (int i = cursor->size; i > 0; i--) {
                cursor->key[i] = cursor->key[i - 1];
            }
            cursor->key[0] = parent->key[leftSibling];
            parent->key[leftSibling] = leftNode->key[leftNode->size - 1];
            for (int i = cursor->size + 1; i > 0; i--) {
                cursor->ptr[i] = cursor->ptr[i - 1];
            }
            cursor->ptr[0] = leftNode->ptr[leftNode->size];
            cursor->size++;
            leftNode->size--;
            return;
        }
    }
    if (rightSibling <= parent->size) {
        Node_usr *rightNode = parent->ptr[rightSibling];
        if (rightNode->size >= (MAX + 1) / 2) {
            cursor->key[cursor->size] = parent->key[pos];
            parent->key[pos] = rightNode->key[0];
            for (int i = 0; i < rightNode->size - 1; i++) {
                rightNode->key[i] = rightNode->key[i + 1];
            }
            cursor->ptr[cursor->size + 1] = rightNode->ptr[0];
            for (int i = 0; i < rightNode->size; ++i) {
                rightNode->ptr[i] = rightNode->ptr[i + 1];
            }
            cursor->size++;
            rightNode->size--;
            return;
        }
    }
    if (leftSibling >= 0) {
        Node_usr *leftNode = parent->ptr[leftSibling];
        leftNode->key[leftNode->size] = parent->key[leftSibling];
        for (int i = leftNode->size + 1, j = 0; j < cursor->size; j++) {
            leftNode->key[i] = cursor->key[j];
        }
        for (int i = leftNode->size + 1, j = 0; j < cursor->size + 1; j++) {
            leftNode->ptr[i] = cursor->ptr[j];
            cursor->ptr[j] = NULL;
        }
        leftNode->size += cursor->size + 1;
        cursor->size = 0;
        removeInternal(parent->key[leftSibling].user_ID, parent, cursor);
    } else if (rightSibling <= parent->size) {
        Node_usr *rightNode = parent->ptr[rightSibling];
        cursor->key[cursor->size] = parent->key[rightSibling - 1];
        for (int i = cursor->size + 1, j = 0; j < rightNode->size; j++) {
            cursor->key[i] = rightNode->key[j];
        }
        for (int i = cursor->size + 1, j = 0; j < rightNode->size + 1; j++) {
            cursor->ptr[i] = rightNode->ptr[j];
            rightNode->ptr[j] = NULL;
        }
        cursor->size += rightNode->size + 1;
        rightNode->size = 0;
        removeInternal(parent->key[rightSibling - 1].user_ID, parent, rightNode);
    }
}

void BPTree_usr::display(Node_usr *cursor=node_usr.getRoot()) {//遍历
    if (cursor != NULL) {
        for (int i = 0; i < cursor->size; i++) {
            cout << cursor->key[i].user_ID<< " ";
        }
        cout << "\n";
        if (cursor->IS_LEAF != true) {
            for (int i = 0; i < cursor->size + 1; i++) {
                display(cursor->ptr[i]);
            }
        }
    }
}
class user_manager
{
public:
    user_manager() {um_password = ""; }
    user_manager(string um_password) : um_password(um_password) {}
    void ShowUserInfo();//展示全部基础用户信息
    void InsertUserInfo(base_user *reader);//录入新基础用户信息
    void QueryUserInfo(string userPW);//根据密码查询读者信息；
    void CancelUser(string userPW);//根据密码删除用户信息

public:
    string um_password;//用户管理员密码
};
void user_manager::ShowUserInfo(){
    node_usr.display();
}

/*
 * 录入新基础用户信息
 * 参数：base_user 类；
 * 功能：无返回值；
 *       展示并录入指定用户信息
*/
void user_manager::InsertUserInfo(base_user *reader){
    //先在用户哈希表内查找是否已经注册
    int key = get_hash(getMD5(reader->password));
    int val = user_password_id.get(key);
    if(val == -1) {//此用户不存在
        User_Register(key, ++total_users); //插入哈希表中
        reader->user_ID=total_users;
        cout << "姓名：" << reader->user_name<<endl;
        cout << "院系：" << reader->user_dep<<endl;
        node_usr.insert(reader); //插入 splay 树
    }
    else {
        cout << "此用户已存在！" << endl;
        return;
    }
}

/*
 * 根据密码查询读者信息
 * 参数：string 型，需要被查询的用户的密码
 * 功能：无返回值；
 *       展示读者基本信息，借书记录与是否冻结；借阅：借书人，书名，借书时间
*/
void user_manager::QueryUserInfo(string userPW){
    int key = get_hash(getMD5(userPW));
    int val = user_password_id.get(key);
    base_user *usr = node_usr.Find(val);//在 splay 树中查询

    cout << "姓名：" << usr->user_name << endl;
    cout << "院系：" << usr->user_dep <<endl;
    cout << "是否被冻结：";
    if(usr->freeze_flag == 0) {
        cout << "否." << endl;
    }
    else cout << "是" << endl;
    cout<<"展示用户: "<<usr->user_name<<"的借书记录!"<<endl;
    for(vector<brorrow_item>::iterator it = usr->bro.begin(); it != usr->bro.end(); it++)
    {
        cout << "借书人名称：" << (*it).borer << endl;
        cout << "书名：" << (*it).script_name << endl;
        cout << "借书时间: " << ctime(&(*it).bro_time) << endl;
    }
}

/*
 * 根据密码删除用户信息
 * 参数：string 型，需要被删除的用户的密码
 * 功能：无返回值；
 *       展示并删除指定用户
*/
void user_manager::CancelUser(string userPW){
    int key = get_hash(getMD5(userPW));
    int val = user_password_id.get(key);
    base_user *usr = node_usr.Find(val);
    if(val == -1) {
        cout << "此用户不存在！" << endl;
        return;
    }

    cout << "姓名：" << usr->user_name;
    cout << "院系：" << usr->user_dep;
    user_password_id.modify(key, 0); //在哈希表中修改
    node_usr.remove(val); //在 splay 中删除
}









/*三类用户注册以及登录界面*/
void UM_register() { //用户管理员注册
    puts("请输入待注册的用户密码:");
    std::string ps;
    std::cin >> ps;
    User_Manager_Register(ps);
    return;
}
void SM_register() { //图书管理员注册
    puts("请输入待注册的图书管理员密码:");
    string ps;
    cin >> ps;
    Script_Manager_Register(ps);
}
void US_register() { //普通用户注册
    base_user user;
    puts("请输入姓名:");
    std::cin >> user.user_name;
    puts("请输入院系:");
    std::cin >> user.user_dep;
    puts("请输入未经注册的密码:");
    std::cin >> user.password;
    user_manager s;
    s.InsertUserInfo(&user);
    vector<base_user*> books;
    node_usr.restore(node_usr.getRoot(), books);
    StoreHash(user_id, script_id, user_password_id, user_manager_password, script_manager_password);
}
void UM_login() { //用户管理员登陆
    string password;
    puts("请输入用户登陆密码:");
    std::cin >> password;
    User_Manager_Authentication(password);
}
void SM_login() { //图书管理员登陆
    string password;
    puts("请输入图书管理员登陆密码:");
    std::cin >> password;
    Script_Manager_Authentication(password);
}
void US_modify() { //用户密码修改
    puts("请输入用户待修改的密码:");
    string password;
    std::cin >> password;
    User_Password_Modify(password);
}
void UM_modify() { //用户管理员密码修改
    puts("请输入用户管理员待修改的密码:");
    string password;
    std::cin >> password;
    User_Manager_Password_Modify(password);
}
void SM_modify() { //图书管理员密码修改
    puts("请输入待修改的密码:");
    string password;
    std::cin >> password;
    Script_Manager_Password_Modify(password);
}
/*基本用户界面*/
base_user *user;
void US_login() { //用户登录
    string password;
    puts("请输入用户登陆密码:");
    std::cin >> password;
    User_Authentication(password);
    int key = get_hash(getMD5(password));
    int val = user_password_id.get(key);
    user = node_usr.Find(val);
}
void brorrowbook() { //用户借书
    puts("图书搜索栏:");
    string name;
    std::cin >> name;
    user->BorrowBook(name);
}
void returnbook() { //用户还书
    puts("待还书的名称:");
    string name;
    std::cin >> name;
    user->ReturnBook(name);
}
void displaymesor() { //用户展示全部的借还信息
    user->DisplayMesBor();
}
void paydet() { //用户偿还欠款
    user->ChangeDebt();
}
/*图书管理员界面*/
script_manager sc_manager;
void restorebook() { //引进图书
    script_item s;
    int n;
    puts("录入新引进的图书:");
    puts("名称:");
    std::cin >> s.name;
    puts("出版社:");
    std::cin >> s.publisher;
    puts("作者:");
    std::cin >> s.Writer;
    puts("ISBN版号:");
    std::cin >> s.ISBN;
    s.res_num = 0;
    puts("单价:");
    std::cin >> s.exp;
    puts("请输入需要录入的数量:");
    std::cin >> n;
    sc_manager.inputbook(&s, n);
}
void remove() { //移除图书
    string name;
    int n;
    puts("请输入需要去除的书名:");
    std::cin >> name;
    puts("请输入移除数目");
    std::cin >> n;
    sc_manager.removebook(name, n);
}
void displaybypublisher() {
    string publisher;
    puts("展示某一出版社下的图书:");
    std::cin >> publisher;
    sc_manager.display_by_publisher(publisher);
}
void displaybywriter() {
    string writer;
    puts("展示某一作者名下全部的图书:");
    std::cin >> writer;
    sc_manager.display_by_writer(writer);
}
void displaybro() { //展示某一图书条目下所有的借还记录
    string name;
    puts("请输入待查询的图书名称:");
    std::cin >> name;
    sc_manager.display_bro(name);
}
/*用户管理员界面*/
user_manager us_manager;
void queryuserinfo() { //查询某一指定密码用户的信息
    puts("请输入待查询的用户的密码:");
    std::string password;
    std::cin >> password;
    us_manager.QueryUserInfo(password);
}
void canceluser() {
    puts("请输入待删除用户的密码:");
    std::string password;
    std::cin >> password;
    us_manager.CancelUser(password);
}
signed main(){
    US_register();
    US_login();
    restorebook();
    brorrowbook();
    brorrowbook();
    brorrowbook();
}
/*
void UM_register();//用户管理员注册
void SM_register(); //图书管理员注册
void US_register(); //普通用户注册
void UM_login();//用户管理员登陆
void SM_login();//图书管理员登陆
void US_modify(); //用户密码修改
void UM_modify(); //用户管理员密码修改
void SM_modify(); //图书管理员密码修改
void US_login();//用户登录
void brorrowbook();//用户借书
void returnbook(); //用户还书
void displaymesor();  //用户展示全部的借还信息
void paydet();  //用户偿还欠款
void restorebook();  //引进图书
void remove();  //移除图书
void displaybypublisher();//展示某一出版社下全部的图书
void displaybywriter();//展示某一作者名下全部的图书
void displaybro();  //展示某一图书条目下所有的借还记录
void queryuserinfo(); //查询某一指定密码用户的信息
void canceluser();
*/